# parameterconfig.py
from fastapi import APIRouter, Depends, HTTPException, Request, Form, Cookie, Query
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
from sqlalchemy.orm import Session
from database import get_db
from models import Parameter, Device
from core.logger import app_logger as logger
from datetime import datetime
from templates import templates
import json
from utils import get_mqtt_client
from paho.mqtt.client import MQTT_ERR_SUCCESS
from utils import validate_session
from typing import Optional
from urllib.parse import quote

router = APIRouter()

# MQTT配置
CONTROL_TOPIC = "/edge_app_controller"

# 初始化MQTT客户端
mqtt_client = get_mqtt_client()

def is_admin_or_deployer(request: Request):
    SessionId = request.cookies.get("SessionId")
    UserName = request.cookies.get("UserName")
    Role = request.cookies.get("Role")
    
    if not SessionId or not UserName or not Role or Role not in ["admin", "deployer"]:
        return False
    return True

def send_mqtt_config_command_to_all(parameter: Parameter, db: Session):
    """发送参数配置到所有设备"""
    if not mqtt_client:
        logger.error("MQTT客户端未初始化，无法发送参数配置")
        return 0, 0
    
    # 获取所有设备
    devices = db.query(Device).all()
    if not devices:
        logger.error("未找到任何设备")
        return 0, 0
    
    # 构建基础消息
    base_payload = {
        "Event": "/alg_config_save",
        "key": parameter.DeviceParameter or parameter.ParameterName,
        "value": parameter.ParameterValue,
        "desc": parameter.ParameterDescription or ""
    }
    
    success_count = 0
    for device in devices:
        try:
            # 为每个设备创建独立消息
            payload = base_payload.copy()
            payload["BoardId"] = device.BoardId
            
            message = json.dumps(payload)
            result, mid = mqtt_client.publish(CONTROL_TOPIC, message)
            
            if result == MQTT_ERR_SUCCESS:
                logger.info(f"参数配置已发送到设备 {device.BoardId}: {parameter.ParameterName}={parameter.ParameterValue} (消息ID: {mid})")
                success_count += 1
            else:
                logger.error(f"向设备 {device.BoardId} 发送失败: 错误码 {result}")
        except Exception as e:
            logger.error(f"向设备 {device.BoardId} 发送时出错: {str(e)}")
    
    total_devices = len(devices)
    return success_count, total_devices

@router.get("/parameterconfig", response_class=HTMLResponse)
async def Parameterconfiguration_page(
    request: Request,
    SessionId: Optional[str] = Cookie(None),
    UserName: Optional[str] = Cookie(None),
    db: Session = Depends(get_db),
    page: int = Query(1, ge=1),
    search: str = Query(None),
    error: str = Query(None),
    success: str = Query(None),
    mqtt_status: str = Query(None),
    sent: int = Query(None),
    total: int = Query(None)
):
    if not SessionId or not UserName or not validate_session(SessionId, UserName):
        return RedirectResponse(url="/")
    # 权限检查（仅管理员可访问）
    if not is_admin_or_deployer(request):
        return RedirectResponse(url="/?error=权限不足")

    # 分页参数
    per_page = 20
    offset = (page - 1) * per_page
    
    # 构建查询 - 只查询未删除的参数(DeadTime为NULL)
    query = db.query(Parameter).filter(Parameter.DeadTime == None)
    
    # 搜索功能
    if search:
        query = query.filter(
            (Parameter.ParameterName.ilike(f"%{search}%")) |
            (Parameter.DeviceParameter.ilike(f"%{search}%")) |
            (Parameter.ParameterValue.ilike(f"%{search}%")) |
            (Parameter.ParameterDescription.ilike(f"%{search}%"))
        )
    
    # 获取参数总数
    total_Parameters = query.count()
    
    # 获取当前页参数
    Parameters = query.order_by(Parameter.ParameterId.asc()).offset(offset).limit(per_page).all()
    
    # 计算总页数
    total_pages = (total_Parameters + per_page - 1) // per_page
    
    # 添加连续序号
    start_number = (page - 1) * per_page + 1
    for index, param in enumerate(Parameters):
        param.display_id = start_number + index

    # 检查MQTT连接状态
    mqtt_connected = False
    if mqtt_client:
        try:
            # 尝试检查连接状态
            mqtt_connected = mqtt_client.is_connected()
        except Exception:
            mqtt_connected = False

    return templates.TemplateResponse("parameterconfig.html", {
        "request": request,
        "Parameters": Parameters,
        "current_page": page,
        "total_pages": total_pages,
        "search": search,
        "error": error,
        "success": success,
        "mqtt_status": mqtt_status,
        "mqtt_connected": mqtt_connected,  # 传递MQTT连接状态
        "sent": sent,  # 成功发送的设备数
        "total": total  # 总设备数
    })

# 添加参数
@router.post("/add_parameter")
async def add_parameter(
    request: Request,
    ParameterName: str = Form(...),
    DeviceParameter: str = Form(...),
    ParameterValue: str = Form(...),
    ParameterDescription: str = Form(...),
    db: Session = Depends(get_db)
):
    # 检查参数名称是否已存在
    existing_param = db.query(Parameter).filter(
        (Parameter.ParameterName == ParameterName)
    ).first()
    
    if existing_param:
        return RedirectResponse(url="/parameterconfig?error=参数名称或设备参数已存在", status_code=303)
    
    # 创建新参数（不再关联特定设备）
    new_Parameter = Parameter(
        ParameterName=ParameterName,
        DeviceParameter=DeviceParameter,
        ParameterValue=ParameterValue,
        ParameterDescription=ParameterDescription,
        BoardId=None  # 不再关联特定设备
    )
    
    try:
        db.add(new_Parameter)
        db.commit()
        
        # 向所有设备发送配置 - 这是新增的功能
        success_count, total_devices = send_mqtt_config_command_to_all(new_Parameter, db)
        
        # 根据发送结果构造不同的成功消息
        if total_devices == 0:
            success_msg = "参数添加成功，但未找到任何设备"
        elif success_count == total_devices:
            success_msg = f"参数添加成功，并已同步到所有设备 ({success_count}/{total_devices})"
        elif success_count > 0:
            success_msg = f"参数添加成功，但只同步到部分设备 ({success_count}/{total_devices})"
        else:
            success_msg = "参数添加成功，但同步到设备失败，请手动同步"
        
        # 编码消息以确保URL安全
        encoded_msg = quote(success_msg)
        return RedirectResponse(
            url=f"/parameterconfig?success={encoded_msg}&mqtt_status=success&sent={success_count}&total={total_devices}", 
            status_code=303
        )
            
    except Exception as e:
        db.rollback()
        logger.error(f"添加参数失败: {str(e)}")
        return RedirectResponse(url="/parameterconfig?error=添加参数失败", status_code=303)

# 编辑参数配置页面
@router.get("/editparameter/{ParameterId}", response_class=HTMLResponse)
async def edit_Parameter_page(
    request: Request,
    ParameterId: int,
    db: Session = Depends(get_db),
    error: str = Query(None)  # 只保留错误提示参数
):
    parameter = db.query(Parameter).filter(Parameter.ParameterId == ParameterId).first()
    if not parameter:
        return RedirectResponse(url="/parameterconfig?error=参数不存在", status_code=303)
    
    # 检查MQTT连接状态
    mqtt_connected = False
    if mqtt_client:
        try:
            mqtt_connected = mqtt_client.is_connected()
        except Exception:
            mqtt_connected = False
    
    return templates.TemplateResponse("editparameter.html", {
        "request": request,
        "parameter": parameter,
        "error": error,  # 只传递错误提示
        "mqtt_connected": mqtt_connected
    })

# 更新参数信息
@router.post("/update_parameter/{ParameterId}")
async def update_Parameter(
    request: Request,
    ParameterId: int,
    ParameterName: str = Form(...),
    DeviceParameter: str = Form(...),
    ParameterValue: str = Form(...),
    ParameterDescription: str = Form(...),
    db: Session = Depends(get_db)
):
    parameter = db.query(Parameter).filter(Parameter.ParameterId == ParameterId).first()
    if not parameter:
        return RedirectResponse(url="/parameterconfig?error=参数不存在", status_code=303)
    
    # 检查参数名称是否已存在（排除当前参数）
    existing_param = db.query(Parameter).filter(
        (Parameter.ParameterName == ParameterName),
        Parameter.ParameterId != ParameterId
    ).first()
    
    if existing_param:
        return RedirectResponse(url=f"/editparameter/{ParameterId}?error=参数名称或设备参数已存在", status_code=303)
    
    # 更新字段（不再关联特定设备）
    parameter.ParameterName = ParameterName
    parameter.DeviceParameter = DeviceParameter
    parameter.ParameterValue = ParameterValue
    parameter.ParameterDescription = ParameterDescription
    parameter.BoardId = None  # 不再关联特定设备
    
    try:
        db.commit()
        # 保存成功后跳转回参数管理页面
        return RedirectResponse(
            url=f"/parameterconfig?success=参数更新成功", 
            status_code=303
        )
            
    except Exception as e:
        db.rollback()
        logger.error(f"更新参数失败: {str(e)}")
        # 保存失败时留在编辑页面
        return RedirectResponse(url=f"/editparameter/{ParameterId}?error=更新参数失败", status_code=303)
    

# 新增路由：发送单个参数到所有设备
@router.post("/send_parameter/{ParameterId}")
async def send_parameter(
    ParameterId: int,
    db: Session = Depends(get_db)
):
    parameter = db.query(Parameter).filter(Parameter.ParameterId == ParameterId).first()
    if not parameter:
        return JSONResponse(
            status_code=404,
            content={"success": False, "message": "参数不存在"}
        )
    
    # 向所有设备发送配置
    success_count, total_devices = send_mqtt_config_command_to_all(parameter, db)
    
    if success_count > 0:
        return {
            "success": True, 
            "message": f"参数已成功发送到 {success_count}/{total_devices} 个设备"
        }
    else:
        return {
            "success": False, 
            "message": "参数发送到所有设备失败"
        }